﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using LDSBusiness.EventArgs;
using LDSModel;
using LDSModel.Dal;
using LDSProject.Forms;
using LDSProject.Properties;
using LDSBusiness;
using LDSCore;

namespace LDSProject.Controls
{
    public partial class MapControl : UserControl
    {
        Dictionary<Guid, List<Data_Records>> _dataList;

        public MapControl()
        {
            InitializeComponent();
        }

        public void Initialization()
        {
            _dataList = new Dictionary<Guid, List<Data_Records>>();

            var index = 1;
            MainConsole.Instance.OilTankPostion.Clear();

            foreach (var oilTank in DeviceService.Instance.OilTankList)
            {
                var pb = new PictureBox { Name = oilTank.OId.ToString(), Tag = "pbOil" + index++ };
                pb.MouseDoubleClick += pb_MouseDoubleClick;
                pb.MouseEnter += MainConsole.Instance.pb_MouseEnter;
                pb.MouseLeave += MainConsole.Instance.pb_MouseLeave;

                pb.BackgroundImage = Resources.device;
                pb.BackgroundImageLayout = ImageLayout.Stretch;
                pb.Cursor = Cursors.Hand;
                pb.SizeMode = PictureBoxSizeMode.StretchImage;

                pb.Image = Resources.offline;
                pb.BackColor = Color.Transparent;
                pb.Enabled = false;

                picMain.Controls.Add(pb);

                _dataList.Add(oilTank.OId, new List<Data_Records>());

                if (oilTank.Left != null)
                    if (oilTank.Top != null)
                        MainConsole.Instance.OilTankPostion.Add(oilTank.OId, new Point(oilTank.Left.Value, oilTank.Top.Value));
            }

            ReSize();

            MainConsole.Instance.OnRecordReceived += Instance_OnRecordReceived;
            MainConsole.Instance.OnOilTankStateChanged += OnOilTankStateChanged;
            MainConsole.Instance.OnPortStop += Instance_OnPortStop;

            timer1.Start();
        }

        void Instance_OnPortStop()
        {
            foreach (Data_OilTank tank in DeviceService.Instance.OilTankList)
            {
                Invoke(new DelegateRefreshDevice(MainConsole.Instance.RefreshPictureBox), this, tank.OId, DeviceState.Offline);
            }

            _dataList.Clear();

            foreach (Data_OilTank oilTank in DeviceService.Instance.OilTankList)
            {
                var pb = picMain.Controls.Find(oilTank.OId.ToString(), false).FirstOrDefault() as PictureBox;
                if (null == pb) continue;
                var panel = Controls.Find(pb.Tag.ToString(), false).FirstOrDefault() as Panel;

                if (!IsDisposed)
                    Invoke(new DelegateRefreshValue(MainConsole.Instance.RefreshValue), oilTank.OId, panel, _dataList, false);
            }
        }

        void OnOilTankStateChanged(object sender, OilTankStateChangedEventArgs args)
        {
            try
            {
                if (!IsDisposed)
                    Invoke(new DelegateRefreshDevice(MainConsole.Instance.RefreshPictureBox), this, args.OId, args.State);
            }
            catch (Exception ex)
            {
                LogFileHelper.Record(ex);
            }
        }

        void Instance_OnRecordReceived(object sender, RecordReceivedEventArgs args)
        {
            try
            {
                var oilTank = DeviceService.Instance.GetOilTankByDeviceId(args.Record.DeviceID);

                if (oilTank == null) return;
                lock (_dataList)
                {
                    List<Data_Records> records;
                    _dataList.TryGetValue(oilTank.OId, out records);

                    if (records == null)
                    {
                        records = new List<Data_Records>();
                    }
                    else
                    {
                        _dataList.Remove(oilTank.OId);
                    }

                    records.Add(args.Record);
                    _dataList.Add(oilTank.OId, records);
                }

                if (!IsDisposed && MainConsole.Instance.CheckAlermValue(args.Record))
                    Invoke(new DelegateRefreshDevice(MainConsole.Instance.RefreshPictureBox), this, oilTank.OId, DeviceState.Alarm);
                var pb = Controls.Find(oilTank.OId.ToString(), true).FirstOrDefault() as PictureBox;
                if (null == pb) return;
                var panel = Controls.Find(pb.Tag.ToString(), false).FirstOrDefault() as Panel;

                if (!IsDisposed)
                    Invoke(new DelegateRefreshValue(MainConsole.Instance.RefreshValue), oilTank.OId, panel, _dataList, false);
            }
            catch (Exception ex)
            {
                LogFileHelper.Record(ex);
            }
        }

        void pb_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Left) return;
            try
            {
                if (!MainConsole.Instance.CheckPortIsOpen(this)) return;
                var form = new OilTankForm(Guid.Parse(((PictureBox)sender).Name));
                form.ShowDialog(this);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            try
            {
                foreach (var oilTank in DeviceService.Instance.OilTankList)
                {
                    List<Data_Records> records;
                    _dataList.TryGetValue(oilTank.OId, out records);

                    if (null != records && records.Count > 0)
                    {
                        records = records.FindAll(r => r.AlarmTime != null && DateTime.Now.Subtract(r.AlarmTime.Value).TotalSeconds < Settings.Default.AlermTimeOut);

                        lock (_dataList)
                        {
                            _dataList.Remove(oilTank.OId);
                            _dataList.Add(oilTank.OId, records);
                        }
                    }

                    var pb = picMain.Controls.Find(oilTank.OId.ToString(), false).FirstOrDefault() as PictureBox;
                    if (null == pb) continue;
                    var panel = Controls.Find(pb.Tag.ToString(), false).FirstOrDefault() as Panel;

                    if (!IsDisposed)
                        Invoke(new DelegateRefreshValue(MainConsole.Instance.RefreshValue), oilTank.OId, panel, _dataList, false);
                }
            }
            catch (Exception ex)
            {
                LogFileHelper.Record(ex);
            }
        }

        private void picMain_Resize(object sender, EventArgs e)
        {
            ReSize();
        }

        private void ReSize()
        {
            var size = new Size(50, 50);
            var blWidth = (float)picMain.Width / picMain.Image.Width;
            var blHeight = (float)picMain.Height / picMain.Image.Height;
            var bl = Math.Min(blWidth, blHeight);
            var offsetWidth = 0;
            var offsetHeight = 0;
            if (blWidth > blHeight)
            {
                offsetWidth = (picMain.Width - (int)(picMain.Image.Width * bl)) / 2;
            }
            else
            {
                offsetHeight = (picMain.Height - (int)(picMain.Image.Height * bl)) / 2;
            }

            //GraphicsPath myPath = new GraphicsPath();
            //myPath.AddEllipse(0, 0, 50, 50);

            foreach (var pic in picMain.Controls.OfType<PictureBox>())
            {
                Point point;
                MainConsole.Instance.OilTankPostion.TryGetValue(Guid.Parse(pic.Name), out point);
                if (!point.IsEmpty)
                {
                    pic.Left = offsetWidth + (int)(point.X * bl);
                    pic.Top = offsetHeight + (int)(point.Y * bl);
                    pic.Width = (int)(size.Width * bl);
                    pic.Height = (int)(size.Height * bl);
                }

                var panel = Controls.Find(pic.Tag.ToString(), true).FirstOrDefault() as Panel;
                if (null == panel) continue;
                panel.Left = pic.Left - panel.Width - 20;
                panel.Top = pic.Top - 20;
            }
        }
    }
}
